#include "dsw3gp.h"

CDsw3gp::CDsw3gp(LPST_ENV_T pEnv, MP4FileHandle h3gp)
: m_pEnv(pEnv)
, m_nWidth(0)
, m_nHeight(0)
, m_nFps(0)
, m_nBitrate(0)
, m_nTotalFrames(0)
, m_h3gp(h3gp)
, m_pSpsLen(NULL)
, m_pPpsLen(NULL)
, m_nCurFrameId(1)
{
	LOG4CPLUS_DEBUG(log_dsw, "Create dsw3gp!");
	MP4GetTrackH264SeqPictHeaders(h3gp, 1, &m_pSps, &m_pSpsLen, &m_pPps, &m_pPpsLen);
	m_nWidth = (int)MP4GetTrackVideoWidth(m_h3gp, 1);
	m_nHeight = (int)MP4GetTrackVideoHeight(m_h3gp, 1);
	m_nFps = (int)MP4GetTrackVideoFrameRate(m_h3gp, 1);
	m_nBitrate = (int)MP4GetTrackBitRate(m_h3gp, 1);
	m_nTotalFrames = (int)MP4GetTrackNumberOfSamples(m_h3gp, 1);
}

CDsw3gp::~CDsw3gp()
{
	LOG4CPLUS_DEBUG(log_dsw, "Destroy dsw3gp!");
	if (m_h3gp != MP4_INVALID_FILE_HANDLE)
		MP4Close(m_h3gp);
}

CDsw3gp* CDsw3gp::createNew(LPST_ENV_T pEnv, char * pFileName)
{
	MP4FileHandle h3gp = MP4Read(pFileName);
	if (h3gp == MP4_INVALID_FILE_HANDLE)
		return NULL;
	return new CDsw3gp(pEnv, h3gp);
}

void CDsw3gp::GetStoreFileResolution(int &nWidth, int &nHeight, int &nBitrate, int &nFps, int &nDuration)
{
	nWidth = m_nWidth;
	nHeight = m_nHeight;
	nBitrate = m_nBitrate;
	nFps = m_nFps;
	nDuration = m_nTotalFrames / m_nFps;
}

void CDsw3gp::SetOffset(int nSeconds)
{
	if (m_h3gp == MP4_INVALID_FILE_HANDLE)
		return;
	int nsid = nSeconds * m_nFps;
	if (nsid == 0)
		nsid = 1;
	if (nsid > m_nTotalFrames)
		nsid = 1;
	int ncount = 0;
	while(MP4GetSampleSync(m_h3gp, 1, nsid) != 1){
		nsid++;
		ncount++;
		if (nsid > m_nTotalFrames)
			nsid = 1;
		if (ncount >= m_nTotalFrames)
			break;
	}
	m_nCurFrameId = nsid;
}

bool CDsw3gp::ReadFrame(unsigned char* pFrame, int &nLen)
{
	if (m_h3gp == MP4_INVALID_FILE_HANDLE)
		return false;
	uint8_t *sample = (uint8_t *)pFrame;
	uint32_t this_size = nLen;
	bool isSyncSample;
	bool bRet = MP4ReadSample(m_h3gp,
		1,
		m_nCurFrameId++,
		&sample,
		&this_size,
		NULL,
		NULL,
		NULL,
		&isSyncSample);
	if (bRet){
		memcpy(pFrame, "\x00\x00\x00\x01", 4);
		nLen = this_size;
		if (isSyncSample){
			int nOffset = *m_pSpsLen + 4 + *m_pPpsLen + 4;
			memmove(pFrame + nOffset, pFrame, nLen);
			unsigned char* pPos = pFrame;
			memcpy(pPos, "\x00\x00\x00\x01", 4);
			pPos += 4;
			memcpy(pPos, *m_pSps, *m_pSpsLen);
			pPos += *m_pSpsLen;
			memcpy(pPos, "\x00\x00\x00\x01", 4);
			pPos += 4;
			memcpy(pPos, *m_pPps, *m_pPpsLen);
			nLen += nOffset;
		}
	}
	return bRet;
}

